package io.finer.erp.jeecg.purchase.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.finer.erp.jeecg.approve.service.impl.ApproveServiceImpl;
import io.finer.erp.jeecg.bas.entity.BasCurrency;
import io.finer.erp.jeecg.bas.entity.BasWarehouse;
import io.finer.erp.jeecg.bas.mapper.BasCurrencyMapper;
import io.finer.erp.jeecg.bas.mapper.BasWarehouseMapper;
import io.finer.erp.jeecg.purchase.entity.PurchaseOrder;
import io.finer.erp.jeecg.purchase.entity.PurchaseOrderLine;
import io.finer.erp.jeecg.purchase.mapper.PurchaseOrderLineMapper;
import io.finer.erp.jeecg.purchase.mapper.PurchaseOrderMapper;
import io.finer.erp.jeecg.purchase.service.PurchaseOrderService;
import io.finer.erp.jeecg.purchase.vo.PurchaseOrderPage;
import io.finer.erp.jeecg.stock.entity.StockMove;
import io.finer.erp.jeecg.stock.service.StockMoveService;
import org.apache.logging.log4j.util.Strings;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.FillRuleUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * <p>
 * 采购订单 服务实现类
 * </p>
 *
 * @author yaoyifan
 * @since 2021-06-15
 */
@Service
public class PurchaseOrderServiceImpl extends ApproveServiceImpl<PurchaseOrderMapper, PurchaseOrder> implements PurchaseOrderService {

    @Autowired
    PurchaseOrderLineMapper purchaseOrderLineMapper;

    @Autowired
    BasWarehouseMapper basWarehouseMapper;

    @Autowired
    BasCurrencyMapper basCurrencyMapper;

    @Autowired
    StockMoveService stockMoveService;

    @Override
    @Transactional
    public void saveMain(PurchaseOrder purchaseOrder, List<PurchaseOrderLine> purchaseOrderLineList) {
        purchaseOrder.setBillProcStatus("create");
        if (Strings.isBlank(purchaseOrder.getBillNo())){
            String bill_no = (String) FillRuleUtil.executeRule("purchase_order_bill_no", null);
            purchaseOrder.setBillNo(bill_no);
        }
        if (Strings.isBlank(purchaseOrder.getCurrencyId())){
            QueryWrapper<BasCurrency> queryWrapper = new QueryWrapper<>();
            String currencyId = basCurrencyMapper.selectOne(queryWrapper.eq("code", "CNY")).getId();
            purchaseOrder.setCurrencyId(currencyId);
        }
        this.baseMapper.insert(purchaseOrder);
        if(purchaseOrderLineList != null && purchaseOrderLineList.size() > 0){
            for(PurchaseOrderLine entity: purchaseOrderLineList){
                entity.setMid(purchaseOrder.getId());
                entity.setBillNo(purchaseOrder.getBillNo());
                purchaseOrderLineMapper.insert(entity);
            }
        }
    }

    @Override
    public IPage<PurchaseOrderPage> selectPurchaseOrderPage(Page page, Wrapper<PurchaseOrderPage> queryWrapper) {
        return this.baseMapper.selectPurchaseOrderPage(page, queryWrapper);
    }

    @Override
    public PurchaseOrderPage selectPurchaseOrderPageById(String id) {
        return this.baseMapper.selectPurchaseOrderPageById(id);
    }

    @Override
    @Transactional
    public void delMain(String id) {
        QueryWrapper<PurchaseOrderLine> queryWrapper = new QueryWrapper<>();
        purchaseOrderLineMapper.delete(queryWrapper.eq("mid",id));
        this.baseMapper.deleteById(id);
    }

    @Override
    public void delBatchMain(Collection<? extends Serializable> idList) {
        for(Serializable id:idList) {
            QueryWrapper<PurchaseOrderLine> queryWrapper = new QueryWrapper<>();
            purchaseOrderLineMapper.delete(queryWrapper.eq("mid",id.toString()));
            this.baseMapper.deleteById(id.toString());
        }
    }

    @Override
    @Transactional
    public void updateMain(PurchaseOrder purchaseOrder, List<PurchaseOrderLine> purchaseOrderLineList) {
        this.baseMapper.updateById(purchaseOrder);
        QueryWrapper<PurchaseOrderLine> queryWrapper = new QueryWrapper<>();
        purchaseOrderLineMapper.delete(queryWrapper.eq("mid",purchaseOrder.getId()));
        if (purchaseOrderLineList != null && purchaseOrderLineList.size() > 0){
            for(PurchaseOrderLine entity: purchaseOrderLineList){
                entity.setMid(purchaseOrder.getId());
                purchaseOrderLineMapper.insert(entity);
            }
        }
    }

    @Override
    @Transactional
    public void submit(String model, String id) {
        super.submit(model, id, this);
        PurchaseOrder purchaseOrder = new PurchaseOrder();
        purchaseOrder.setId(id);
        purchaseOrder.setBillProcStatus("submit");
        this.baseMapper.updateById(purchaseOrder);
    }

    @Override
    @Transactional
    public void reject(String model, String id, String note) {
        super.reject(model, id, note);
        PurchaseOrder purchaseOrder = new PurchaseOrder();
        purchaseOrder.setId(id);
        purchaseOrder.setBillProcStatus("reject");
        this.baseMapper.updateById(purchaseOrder);
    }

    @Override
    @Transactional
    public String approve(String model, String id, String note) {
        String approveInstanceStatus = super.approve(model, id, note);
        PurchaseOrder purchaseOrder = new PurchaseOrder();
        purchaseOrder.setId(id);
        purchaseOrder.setBillProcStatus(approveInstanceStatus);
        this.baseMapper.updateById(purchaseOrder);
        if ("approve_complete".equals(approveInstanceStatus)){
            createStockMove(id);
        }
        return approveInstanceStatus;
    }

    @Override
    @Transactional
    public void withDraw(String model, String id) {
        super.withDraw(model, id);
        PurchaseOrder purchaseOrder = new PurchaseOrder();
        purchaseOrder.setId(id);
        purchaseOrder.setBillProcStatus("create");
        this.baseMapper.updateById(purchaseOrder);
    }

    @Transactional
    public void invalid(String id, String note) {
        PurchaseOrder purchaseOrder = new PurchaseOrder();
        purchaseOrder.setId(id);
        purchaseOrder.setBillProcStatus("invalid");
        purchaseOrder.setInvalidationReason(note);
        this.baseMapper.updateById(purchaseOrder);
    }

    @Override
    @Transactional
    public void createStockMove(String id) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        QueryWrapper<PurchaseOrderLine> purchaseOrderLineQueryWrapper = new QueryWrapper<>();
        QueryWrapper<BasWarehouse> basWarehouseQueryWrapper = new QueryWrapper<>();
        BasWarehouse basWarehouse = basWarehouseMapper.selectOne(basWarehouseQueryWrapper.eq("location_type", "供应商库位"));
        PurchaseOrder purchaseOrder = this.baseMapper.selectById(id);
        List<PurchaseOrderLine> purchaseOrderLineList = purchaseOrderLineMapper.selectList(purchaseOrderLineQueryWrapper.eq("mid", id));
        int i = 1;
        for (PurchaseOrderLine purchaseOrderLine: purchaseOrderLineList) {
            StockMove stockMove = new StockMove();
            stockMove.setMaterialId(purchaseOrderLine.getMaterialId());
            stockMove.setQty(purchaseOrderLine.getQty());
            stockMove.setPrice(purchaseOrderLine.getPrice());
            stockMove.setSourceWarehouseId(basWarehouse.getId());
            stockMove.setDestWarehouseId(purchaseOrderLine.getDestWarehouseId());
            stockMove.setTransactionType("采购入库");
            stockMove.setSysOrgCode(purchaseOrderLine.getSysOrgCode());
            stockMove.setProcessor(sysUser.getUsername());
            stockMove.setOrigin(purchaseOrderLine.getBillNo());
            stockMove.setRef(purchaseOrderLine.getBillNo() + "-" + i + "-" + purchaseOrderLine.getId());
            stockMove.setRefId(purchaseOrderLine.getId());
            stockMove.setAmount(purchaseOrderLine.getLineAmount());
            stockMove.setSupplierId(purchaseOrder.getSupplierId());
            stockMove.setRemark(purchaseOrderLine.getRemark());
            stockMove.setState("可用");
            stockMoveService.save(stockMove);
        }
    }

    @Override
    @Transactional
    public void updateState(String billNo) {
        QueryWrapper<PurchaseOrder> purchaseOrderQueryWrapper = new QueryWrapper<>();
        purchaseOrderQueryWrapper.eq("bill_no", billNo);
        PurchaseOrder purchaseOrder = this.baseMapper.selectOne(purchaseOrderQueryWrapper);
        QueryWrapper<PurchaseOrderLine> purchaseOrderLineQueryWrapper = new QueryWrapper<>();
        purchaseOrderLineQueryWrapper.eq("mid", purchaseOrder.getId());
        List<PurchaseOrderLine> purchaseOrderLineList = purchaseOrderLineMapper.selectList(purchaseOrderLineQueryWrapper);
        int partReceipt = 0;
        int complete = 0;
        for (PurchaseOrderLine purchaseOrderLine : purchaseOrderLineList) {
            if("部分入库".equals(purchaseOrderLine.getLineState())){
                partReceipt += 1;
            }else if("完成".equals(purchaseOrderLine.getLineState())){
                complete += 1;
            }
        }
        if (partReceipt > 0){
            purchaseOrder.setBillProcStatus("部分入库");
        }else if(complete > 0 && complete < purchaseOrderLineList.size()){
            purchaseOrder.setBillProcStatus("部分入库");
        }else if(complete == purchaseOrderLineList.size()){
            purchaseOrder.setBillProcStatus("完成");
        }
        this.baseMapper.updateById(purchaseOrder);
    }
}
